package factory

import (
	"blockchain/bccsp"
	"github.com/pkg/errors"
)

// FactoryOpts保存用于初始化工厂实现的配置信息
type FactoryOpts struct {
	Default string  `json:"default" yaml:"Default"`           //不存在默认为SW
	SW      *SwOpts `json:"SW,omitempty" yaml:"SW,omitempty"` //不存在默认为SW的配置信息
}

//在使用工厂接口之前必须调用InitFactories
//可以使用config = nil调用，在这种情况下会使用一些默认值
//只有当defaultBCCSP不存在时才返回错误
func InitFactories(config *FactoryOpts) error {
	factoriesInitOnce.Do(func() {
		factoriesInitError = initFactories(config)
	})

	return factoriesInitError
}

// 初始化工厂
func initFactories(config *FactoryOpts) error {
	//
	if config == nil {
		config = GetDefaultOpts()
	}
	// Default
	if config.Default == "" {
		config.Default = "SW"
	}

	if config.SW == nil {
		config.SW = GetDefaultOpts().SW
	}

	// 如果是软件为基础的SW
	if config.Default == "SW" && config.SW != nil {
		f := &SWFactory{}
		var err error
		defaultBCCSP, err = initBCCSP(f, config)
		if err != nil {
			return errors.Wrapf(err, "Failed initializing BCCSP")
		}
	}

	if defaultBCCSP == nil {
		return errors.Errorf("Could not find default `%s` BCCSP", config.Default)
	}

	return nil
}

//从opts获得一个Factory
func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error) {
	var f BCCSPFactory
	switch config.Default {
	case "SW":
		f = &SWFactory{}
	default:
		return nil, errors.Errorf("Could not find BCCSP, no '%s' provider", config.Default)
	}

	csp, err := f.Get(config)
	if err != nil {
		return nil, errors.Wrapf(err, "Could not initialize BCCSP %s", f.Name())
	}
	return csp, nil
}

// GetDefaultOpts提供了Opts的默认实现
// 每次返回一个新实例
func GetDefaultOpts() *FactoryOpts {
	return &FactoryOpts{
		Default: "SW",
		SW: &SwOpts{
			Hash:     "SHA2",
			Security: 256,
		},
	}
}

// FactoryName返回提供程序的名称
func (o *FactoryOpts) FactoryName() string {
	return o.Default
}
